<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 Events
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora049.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora051.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> Events</H2>
<A NAME="@concepts116"></A>The handling of events produced in the graphical window allows interaction
between the user and the program. <TT>Graphics</TT> supports the treating
of events like keystrokes, mouse clicks and movements of the mouse.<BR>
<BR>
The programming style therefore changes the organization of the program.
It becomes an infinite loop waiting for events. After handling each
newly triggered event, the program returns to the infinite loop except
for events that indicate program termination.<BR>
<BR>
<A NAME="toc66"></A>
<H3> Types and functions for events</H3>
<A NAME="sec-fn-event"></A>
<A NAME="@fonctions175"></A>
<A NAME="@fonctions176"></A>
<A NAME="@fonctions177"></A>
The main function for waiting for events is
<TT>wait_next_event</TT> of type <I>event list -&gt; status</I>. <BR>
<BR>
The different events are given by the sum type
<I>event</I>. 


<PRE><BR><B>type</B><CODE> </CODE>event<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Button_down<CODE> </CODE><CODE>|</CODE><CODE> </CODE>Button_up<CODE> </CODE><CODE>|</CODE><CODE> </CODE>Key_pressed<CODE> </CODE><CODE>|</CODE><CODE> </CODE>Mouse_motion<CODE> </CODE><CODE>|</CODE><CODE> </CODE>Poll;;<BR>

</PRE>

The four main values correspond to pressing and to releasing a mouse
button, to movement of the mouse and to keystrokes. Waiting for an
event is a blocking operation except if the constructor <TT>Poll</TT>
is passed in the event list. This function returns a value of type
<I>status</I>:


<PRE><BR><B>type</B><CODE> </CODE>status<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE>{<CODE> </CODE>mouse_x<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>mouse_y<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>button<CODE> </CODE><CODE>:</CODE><CODE> </CODE>bool;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>keypressed<CODE> </CODE><CODE>:</CODE><CODE> </CODE>bool;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>key<CODE> </CODE><CODE>:</CODE><CODE> </CODE>char};;<BR>

</PRE>
<BR>
<BR>
This is a record containing the position of the mouse, a Boolean which
indicates whether a mouse button is being pressed, another Boolean for
the keyboard and a character which corresponds to the pressed key. The
following functions exploit the data contained in the event record:
<A NAME="@fonctions178"></A>
<A NAME="@fonctions179"></A>
<A NAME="@fonctions180"></A>
<A NAME="@fonctions181"></A>
<UL>
<LI>
 <TT>mouse_pos</TT>: <I>unit -&gt; int * int</I>: returns the
position of the mouse with respect to the window. If the mouse is placed
elsewhere, the coordinates are outside the borders of the window.

<LI> <TT>button_down</TT>: <I>unit -&gt; bool</I>: indicates pressing
of a mouse button.

<LI> <TT>read_key</TT>: <I>unit -&gt; char</I>: fetches a character
typed on the keyboard; this operation blocks.

<LI> <TT>key_pressed</TT>: <I>unit -&gt; bool</I>: indicates whether
a key is being pressed on the keyboard; this operation does not block.
</UL>The handling of events supported by <TT>Graphics</TT> is indeed
minimal for developing interactive interfaces. Nevertheless, the code
is portable across various graphical systems like Windows, MacOS
or X-Windows. This is the reason why this library does not take into
account different mouse buttons. In fact, the Mac does not even possess
more than one. Other events, such as exposing a window or changing its
size are not accessible and are left to the control of the library.<BR>
<BR>
<A NAME="toc67"></A>
<H3> Program skeleton</H3>
<A NAME="sec-squelette"></A>
All programs implementing a graphical user interface make use
of a potentially infinite loop waiting for user interaction. As
soon as an action arrives, the program executes the job associated
with this action. The following function possesses five parameters
of functionals. The first two serve for starting and closing the
application. The next two arguments handle keyboard and mouse events. The
last one permits handling of exceptions that escape out of the different
functions of the application. We assume that the events associated with
terminating the application raise the exception <TT>End</TT>.


<PRE><BR># <B>exception</B><CODE> </CODE>End;;<BR><CODE>exception End</CODE><BR># <B>let</B><CODE> </CODE>skel<CODE> </CODE>f_init<CODE> </CODE>f_end<CODE> </CODE>f_key<CODE> </CODE>f_mouse<CODE> </CODE>f_except<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE>f_init<CODE> </CODE>();<BR><CODE> </CODE><CODE> </CODE><B>try</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>while</B><CODE> </CODE><B>true</B><CODE> </CODE><B>do</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>try</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Graphics.wait_next_event<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>[</CODE>Graphics<CODE>.</CODE>Button_down;<CODE> </CODE>Graphics<CODE>.</CODE>Key_pressed<CODE>]</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><B>if</B><CODE> </CODE>s<CODE>.</CODE>Graphics.keypressed<CODE> </CODE><B>then</B><CODE> </CODE>f_key<CODE> </CODE>s<CODE>.</CODE>Graphics.key<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>else</B><CODE> </CODE><B>if</B><CODE> </CODE>s<CODE>.</CODE>Graphics.button<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>then</B><CODE> </CODE>f_mouse<CODE> </CODE>s<CODE>.</CODE>Graphics.mouse_x<CODE> </CODE>s<CODE>.</CODE>Graphics.mouse_y<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>with</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>End<CODE> </CODE>-&gt;<CODE> </CODE>raise<CODE> </CODE>End<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE> </CODE>e<CODE> </CODE><CODE> </CODE>-&gt;<CODE> </CODE>f_except<CODE> </CODE>e<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>done</B><BR><CODE> </CODE><CODE> </CODE><B>with</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>End<CODE> </CODE><CODE> </CODE>-&gt;<CODE> </CODE>f_end<CODE> </CODE>();;<BR><CODE>val skel :</CODE><BR><CODE>  (unit -&gt; 'a) -&gt;</CODE><BR><CODE>  (unit -&gt; unit) -&gt;</CODE><BR><CODE>  (char -&gt; unit) -&gt; (int -&gt; int -&gt; unit) -&gt; (exn -&gt; unit) -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>
 <BR>
<BR>
Here, we use the skeleton to implement a mini-editor. Touching a key
displays the typed character. A mouse click changes the current point. The
character '&amp;' exits the program. The only difficulty in this program is
line breaking. We assume as simplification that the height of characters
does not exceed twelve pixels.


<PRE><BR># <B>let</B><CODE> </CODE>next_line<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<TT>)</TT><CODE> </CODE><CODE>=</CODE><CODE> </CODE>Graphics.current_point()<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><B>if</B><CODE> </CODE>y<CODE>&gt;</CODE><CODE>1</CODE><CODE>2</CODE><CODE> </CODE><B>then</B><CODE> </CODE>Graphics.moveto<CODE> </CODE><CODE>0</CODE><CODE> </CODE><TT>(</TT>y<CODE>-</CODE><CODE>1</CODE><CODE>2</CODE><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>else</B><CODE> </CODE>Graphics.moveto<CODE> </CODE><CODE>0</CODE><CODE> </CODE>y;;<BR><CODE>val next_line : unit -&gt; unit = &lt;fun&gt;</CODE><BR># <B>let</B><CODE> </CODE>handle_char<CODE> </CODE>c<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>match</B><CODE> </CODE>c<CODE> </CODE><B>with</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>'&amp;'</CODE><CODE> </CODE><CODE> </CODE>-&gt;<CODE> </CODE>raise<CODE> </CODE>End<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>'\n'</CODE><CODE> </CODE>-&gt;<CODE> </CODE>next_line<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>'\r'</CODE><CODE> </CODE>-&gt;<CODE> </CODE>next_line<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE><CODE> </CODE>-&gt;<CODE> </CODE>Graphics.draw_char<CODE> </CODE>c;;<BR><CODE>val handle_char : char -&gt; unit = &lt;fun&gt;</CODE><BR># <B>let</B><CODE> </CODE>go<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>skel<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>()<CODE> </CODE>-&gt;<CODE> </CODE>Graphics.clear_graph<CODE> </CODE>();<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.moveto<CODE> </CODE><CODE>0</CODE><CODE> </CODE><TT>(</TT>Graphics.size_y()<CODE> </CODE><CODE>-</CODE><CODE>1</CODE><CODE>2</CODE><TT>)</TT><CODE> </CODE><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>()<CODE> </CODE>-&gt;<CODE> </CODE>Graphics.clear_graph()<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>handle_char<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>-&gt;<CODE> </CODE>Graphics.moveto<CODE> </CODE>x<CODE> </CODE>y<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><B>fun</B><CODE> </CODE>e<CODE> </CODE>-&gt;<CODE> </CODE>()<TT>)</TT>;;<BR><CODE>val go : unit -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>

This program does not handle deletion of characters by pressing the
key <CODE>DEL</CODE>.<BR>
<BR>
<A NAME="toc68"></A>
<H3> Example: telecran</H3>
Telecran is a little drawing game for training coordination of movements.
A point appears on a slate. This point can be moved in directions X and
Y by using two control buttons for these axes without ever releasing the
pencil. We try to simulate this behavior to illustrate the interaction
between a program and a user. To do this we reuse the previously described
skeleton. We will use certain keys of the keyboard to indicate movement
along the axes.<BR>
<BR>
We first define the type <I>state</I>, which is a record describing
the size of the slate in terms of the number of positions in X and Y, the
current position of the point and the scaling factor for visualization,
the color of the trace, the background color and the color of the
current point.


<PRE><BR># <B>type</B><CODE> </CODE>state<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{maxx<CODE>:</CODE>int;<CODE> </CODE>maxy<CODE>:</CODE>int;<CODE> </CODE><B>mutable</B><CODE> </CODE>x<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int;<CODE> </CODE><B>mutable</B><CODE> </CODE>y<CODE> </CODE><CODE>:</CODE>int;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>scale<CODE>:</CODE>int;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>bc<CODE> </CODE><CODE>:</CODE><CODE> </CODE>Graphics.color;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>fc<CODE>:</CODE><CODE> </CODE>Graphics.color;<CODE> </CODE>pc<CODE> </CODE><CODE>:</CODE><CODE> </CODE>Graphics.color};;<BR>

</PRE>
<BR>
<BR>
The function <TT>draw_point</TT> displays a point given its coordinates,
the scaling factor and its color.


<PRE><BR># <B>let</B><CODE> </CODE>draw_point<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE>s<CODE> </CODE>c<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.set_color<CODE> </CODE>c;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.fill_rect<CODE> </CODE><TT>(</TT>s<CODE>*</CODE>x<TT>)</TT><CODE> </CODE><TT>(</TT>s<CODE>*</CODE>y<TT>)</TT><CODE> </CODE>s<CODE> </CODE>s;;<BR><CODE>val draw_point : int -&gt; int -&gt; int -&gt; Graphics.color -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
All these functions for initialization, handling of user interaction and
exiting the program receive a parameter corresponding to the state. The
first four functions are defined as follows:


<PRE><BR># <B>let</B><CODE> </CODE>t_init<CODE> </CODE>s<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.open_graph<CODE> </CODE><TT>(</TT><CODE>" "</CODE><CODE> </CODE><CODE>^</CODE><CODE> </CODE><TT>(</TT>string_of_int<CODE> </CODE><TT>(</TT>s<CODE>.</CODE>scale<CODE>*</CODE>s<CODE>.</CODE>maxx<TT>)</TT><TT>)</TT><CODE> </CODE><CODE>^</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>"x"</CODE><CODE> </CODE><CODE>^</CODE><CODE> </CODE><TT>(</TT>string_of_int<CODE> </CODE><TT>(</TT>s<CODE>.</CODE>scale<CODE>*</CODE>s<CODE>.</CODE>maxy<TT>)</TT><TT>)</TT><TT>)</TT>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.set_color<CODE> </CODE>s<CODE>.</CODE>bc;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.fill_rect<CODE> </CODE><CODE>0</CODE><CODE> </CODE><CODE>0</CODE><CODE> </CODE><TT>(</TT>s<CODE>.</CODE>scale<CODE>*</CODE>s<CODE>.</CODE>maxx<CODE>+</CODE><CODE>1</CODE><TT>)</TT><CODE> </CODE><TT>(</TT>s<CODE>.</CODE>scale<CODE>*</CODE>s<CODE>.</CODE>maxy<CODE>+</CODE><CODE>1</CODE><TT>)</TT>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>draw_point<CODE> </CODE>s<CODE>.</CODE>x<CODE> </CODE>s<CODE>.</CODE>y<CODE> </CODE>s<CODE>.</CODE>scale<CODE> </CODE>s<CODE>.</CODE>pc;;<BR><CODE>val t_init : state -&gt; unit -&gt; unit = &lt;fun&gt;</CODE><BR># <B>let</B><CODE> </CODE>t_end<CODE> </CODE>s<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.close_graph();<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>print_string<CODE> </CODE><CODE>"Good bye..."</CODE>;<CODE> </CODE>print_newline();;<BR><CODE>val t_end : 'a -&gt; unit -&gt; unit = &lt;fun&gt;</CODE><BR># <B>let</B><CODE> </CODE>t_mouse<CODE> </CODE>s<CODE> </CODE>x<CODE> </CODE>y<CODE> </CODE><CODE>=</CODE><CODE> </CODE>();;<BR><CODE>val t_mouse : 'a -&gt; 'b -&gt; 'c -&gt; unit = &lt;fun&gt;</CODE><BR># <B>let</B><CODE> </CODE>t_except<CODE> </CODE>s<CODE> </CODE>ex<CODE> </CODE><CODE>=</CODE><CODE> </CODE>();;<BR><CODE>val t_except : 'a -&gt; 'b -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
The function <TT>t_init</TT> opens the graphical window and displays the
current point, <TT>t_end</TT> closes this window and displays a message,
<TT>t_mouse</TT> and <TT>t_except</TT> do not do anything. The program
handles neither mouse events nor exceptions which may accidentally arise
during program execution. The important function is the one for handling
the keyboard <TT>t_key</TT>:


<PRE><BR># <B>let</B><CODE> </CODE>t_key<CODE> </CODE>s<CODE> </CODE>c<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE>draw_point<CODE> </CODE>s<CODE>.</CODE>x<CODE> </CODE>s<CODE>.</CODE>y<CODE> </CODE>s<CODE>.</CODE>scale<CODE> </CODE>s<CODE>.</CODE>fc;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><B>match</B><CODE> </CODE>c<CODE> </CODE><B>with</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>'8'</CODE><CODE> </CODE>-&gt;<CODE> </CODE><B>if</B><CODE> </CODE>s<CODE>.</CODE>y<CODE> </CODE><CODE>&lt;</CODE><CODE> </CODE>s<CODE>.</CODE>maxy<CODE> </CODE><B>then</B><CODE> </CODE><CODE> </CODE>s<CODE>.</CODE>y<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>s<CODE>.</CODE>y<CODE> </CODE><CODE>+</CODE><CODE> </CODE><CODE>1</CODE>;<CODE> </CODE><CODE> </CODE><BR><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>'2'</CODE><CODE> </CODE>-&gt;<CODE> </CODE><B>if</B><CODE> </CODE>s<CODE>.</CODE>y<CODE> </CODE><CODE>&gt;</CODE><CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>then</B><CODE> </CODE>s<CODE>.</CODE>y<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>s<CODE>.</CODE>y<CODE> </CODE><CODE>-</CODE><CODE> </CODE><CODE>1</CODE><BR><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>'4'</CODE><CODE> </CODE>-&gt;<CODE> </CODE><B>if</B><CODE> </CODE>s<CODE>.</CODE>x<CODE> </CODE><CODE>&gt;</CODE><CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>then</B><CODE> </CODE>s<CODE>.</CODE>x<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>s<CODE>.</CODE>x<CODE> </CODE><CODE>-</CODE><CODE> </CODE><CODE>1</CODE><CODE> </CODE><BR><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>'6'</CODE><CODE> </CODE>-&gt;<CODE> </CODE><B>if</B><CODE> </CODE>s<CODE>.</CODE>x<CODE> </CODE><CODE>&lt;</CODE><CODE> </CODE>s<CODE>.</CODE>maxx<CODE> </CODE><B>then</B><CODE> </CODE>s<CODE>.</CODE>x<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>s<CODE>.</CODE>x<CODE> </CODE><CODE>+</CODE><CODE> </CODE><CODE>1</CODE><CODE> </CODE><BR><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>'c'</CODE><CODE> </CODE>-&gt;<CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.set_color<CODE> </CODE>s<CODE>.</CODE>bc;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.fill_rect<CODE> </CODE><CODE>0</CODE><CODE> </CODE><CODE>0</CODE><CODE> </CODE><TT>(</TT>s<CODE>.</CODE>scale<CODE>*</CODE>s<CODE>.</CODE>maxx<CODE>+</CODE><CODE>1</CODE><TT>)</TT><CODE> </CODE><TT>(</TT>s<CODE>.</CODE>scale<CODE>*</CODE>s<CODE>.</CODE>maxy<CODE>+</CODE><CODE>1</CODE><TT>)</TT>;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>Graphics.clear_graph()<BR><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>'e'</CODE><CODE> </CODE>-&gt;<CODE> </CODE>raise<CODE> </CODE>End<BR><CODE> </CODE><CODE>|</CODE><CODE> </CODE><CODE>_</CODE><CODE> </CODE>-&gt;<CODE> </CODE>()<TT>)</TT>;<BR><CODE> </CODE><CODE> </CODE>draw_point<CODE> </CODE>s<CODE>.</CODE>x<CODE> </CODE>s<CODE>.</CODE>y<CODE> </CODE>s<CODE>.</CODE>scale<CODE> </CODE>s<CODE>.</CODE>pc;;<BR><CODE>val t_key : state -&gt; char -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
It displays the current point in the color of the trace. Depending
on the character passed, it modifies, if possible, the coordinates of
the current point (characters: '2', '4', '6', '8'), clears the screen
(character: 'c') or raises the exception <TT>End</TT> (character: 'e'),
then it displays the new current point. Other characters are ignored. The
choice of characters for moving the cursor comes from the layout of the
numeric keyboard: the chosen keys correspond to the indicated digits and
to the direction arrows. It is therefore useful to activate the numeric
keyboard for the ergonomics of the program.<BR>
<BR>
We finally define a state and apply the skeleton function in the
following way:


<PRE><BR># <B>let</B><CODE> </CODE>stel<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{maxx<CODE>=</CODE><CODE>1</CODE><CODE>2</CODE><CODE>0</CODE>;<CODE> </CODE>maxy<CODE>=</CODE><CODE>1</CODE><CODE>2</CODE><CODE>0</CODE>;<CODE> </CODE>x<CODE>=</CODE><CODE>6</CODE><CODE>0</CODE>;<CODE> </CODE>y<CODE>=</CODE><CODE>6</CODE><CODE>0</CODE>;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>scale<CODE>=</CODE><CODE>4</CODE>;<CODE> </CODE>bc<CODE>=</CODE>Graphics.rgb<CODE> </CODE><CODE>1</CODE><CODE>3</CODE><CODE>0</CODE><CODE> </CODE><CODE>1</CODE><CODE>3</CODE><CODE>0</CODE><CODE> </CODE><CODE>1</CODE><CODE>3</CODE><CODE>0</CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>fc<CODE>=</CODE>Graphics.black;<CODE> </CODE>pc<CODE>=</CODE>Graphics.red};;<BR><CODE>val stel : state =</CODE><BR><CODE>  {maxx=120; maxy=120; x=60; y=60; scale=4; bc=8553090; fc=0; pc=16711680}</CODE><BR># <B>let</B><CODE> </CODE>slate<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE>skel<CODE> </CODE><TT>(</TT>t_init<CODE> </CODE>stel<TT>)</TT><CODE> </CODE><CODE> </CODE><TT>(</TT>t_end<CODE> </CODE>stel<TT>)</TT><CODE> </CODE><TT>(</TT>t_key<CODE> </CODE>stel<TT>)</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT>t_mouse<CODE> </CODE>stel<TT>)</TT><CODE> </CODE><TT>(</TT>t_except<CODE> </CODE>stel<TT>)</TT>;;<BR><CODE>val slate : unit -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
Calling function <TT>slate</TT> displays the graphical window, then it
waits for user interaction on the keyboard.
Figure <A HREF="book-ora050.html#fig-telecran">5.8</A> shows a drawing created with this program.
<BLOCKQUOTE><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV>
<DIV ALIGN=center>
<IMG SRC="book-ora017.gif">
</DIV>
<BR>
<DIV ALIGN=center>Figure 5.8: Telecran.</DIV><BR>

<A NAME="fig-telecran"></A>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></BLOCKQUOTE><HR>
<A HREF="book-ora049.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora051.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
